using System;

using CoreCalc;

using RayDen.Library.Core.Primitives;
using RayDen.Library.Data.Imaging;

namespace RayDen.Library.Components.Color
{
    public class SpectralRadiance : RadianceEvaluationBase<SampledSpectrum>
    {

        public static SpectralRadiance Zero = new SpectralRadiance(SampledSpectrum.ZeroSpectrum());
        public static SpectralRadiance Unit = new SpectralRadiance(SampledSpectrum.UnitSpectrum());

        public SpectralRadiance(ref SampledSpectrum spc)
            : base(ref spc)
        {
        }

        public SpectralRadiance(SampledSpectrum spc)
            : base(spc)
        {
        }

        public SpectralRadiance(RadianceEvaluationBase<SampledSpectrum> val)
            : base(val)
        {
        }

        protected override IRadianceEvaluation Convert(IRadianceEvaluation val)
        {
            if (val is RgbRadiance)
            {
                var value = (val as RgbRadiance);
                return new SpectralRadiance(ColorFactory.SSEFromRgb(val.ToArray()));
            }
            else if (val is FloatRadiance)
            {
                var value = (val as FloatRadiance);
                return new SpectralRadiance(new SampledSpectrum(value.Spectra));
            }
            return val;
        }

        public override IRadianceEvaluation Mul(float value)
        {
            SSE.MulSSE(ref Spectra, value, ref Spectra);

            return this;
        }

        public override IRadianceEvaluation Add(float value)
        {
            //this.Spectra += value;
            SSE.AddSSE(ref Spectra, value, ref Spectra);
            return this;
        }

        public override IRadianceEvaluation Div(float value)
        {
            SSE.MulSSE(ref Spectra, 1f / value, ref Spectra);

            return this;
        }

        public override void ToRgbSpectrum(out RgbSpectrum result)
        {
            result = this.Spectra.ToRgb();
        }

        public override float[] ToArray()
        {
            return this.Spectra.ToArray();
        }

        protected override RadianceEvaluationBase<SampledSpectrum> Multiply(RadianceEvaluationBase<SampledSpectrum> val)
        {
            //this.Spectra *= val.Spectra;
            SSE.MulSSE(ref Spectra, ref val.Spectra, ref Spectra);
            return this;
        }

        protected override RadianceEvaluationBase<SampledSpectrum> Add(RadianceEvaluationBase<SampledSpectrum> val)
        {
            //this.Spectra += val.Spectra;
            SSE.AddSSE(ref Spectra, ref val.Spectra, ref Spectra);
            return this;
        }

        public override bool IsBlack
        {
            get { return this.Spectra.IsBlack(); }
            protected set { throw new NotImplementedException(); }
        }

        public override IRadianceEvaluation Clone()
        {
            return new SpectralRadiance(this);
        }
    }
}